package com.nuoniu.sibanyun.service.msg.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nuoniu.sibanyun.entity.SysMenu;
import com.nuoniu.sibanyun.entity.SysUser;
import com.nuoniu.sibanyun.entity.crm.call.rongying.RongYingCallState;
import com.nuoniu.sibanyun.entity.erp.in.InInventory;
import com.nuoniu.sibanyun.entity.erp.in.VInventoryCheckMain;
import com.nuoniu.sibanyun.entity.inOut.VInOutAllocationMain;
import com.nuoniu.sibanyun.entity.inOut.VInOutRecordDetail;
import com.nuoniu.sibanyun.entity.inOut.VInOutRecordMain;
import com.nuoniu.sibanyun.entity.msg.SysMsg;
import com.nuoniu.sibanyun.entity.so.VSaleDeliveryMain;
import com.nuoniu.sibanyun.entity.vo.MenuVo;
import com.nuoniu.sibanyun.entity.webSocket.WebSocketResult;
import com.nuoniu.sibanyun.mapper.msg.SysMsgMapper;
import com.nuoniu.sibanyun.service.ISysUserService;
import com.nuoniu.sibanyun.service.erp.in.IInInventoryInfoService;
import com.nuoniu.sibanyun.service.erp.in.IInInventoryService;
import com.nuoniu.sibanyun.service.msg.ISysMsgService;
import com.nuoniu.sibanyun.service.msg.WebSocketService;
import com.nuoniu.sibanyun.userThread.UserInfo;
import com.nuoniu.sibanyun.userThread.UserThreadLocal;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 消息管理 服务实现类
 * </p>
 *
 * @author 小啊刚
 * @since 2022-01-07
 */
@Service
public class SysMsgServiceImpl extends ServiceImpl<SysMsgMapper, SysMsg> implements ISysMsgService {

    @Autowired
    private IInInventoryInfoService inventoryInfoService;
    @Autowired
    private IInInventoryService inventoryService;
    @Autowired
    @Lazy
    private ISysUserService userService;
    @Autowired
    private WebSocketService socketService;

    @Override
    public Integer getMsgCount(Integer type, Integer status) {
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("user_id", UserThreadLocal.get().getUserId());
        if(type != null) {
            wrapper.eq("type", type);
        }

        if(status != null) {
            wrapper.eq("status", status);
        }

        return this.count(wrapper);
    }

    @Override
    public Page<SysMsg> pageList(Page page, Integer type, Integer status) {
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("user_id", UserThreadLocal.get().getUserId());
        if(type != null) {
            wrapper.eq("type", type);
        }

        if(status != null) {
            wrapper.eq("status", status);
        }

        wrapper.orderByAsc("status");
        wrapper.orderByDesc("create_date");
        return page(page, wrapper);
    }

    @Override
    public void readMsg(List<Long> ids) {
        UpdateWrapper wrapper = new UpdateWrapper();
        wrapper.in("id", ids);
        wrapper.eq("user_id", UserThreadLocal.get().getUserId());
        wrapper.set("status", 1);
        wrapper.set("update_date", LocalDateTime.now());
        this.update(wrapper);

        sendSocketMsg(UserThreadLocal.get().getUserId());
    }

    @Override
    public void realAll() {
        UpdateWrapper wrapper = new UpdateWrapper();
        wrapper.eq("user_id", UserThreadLocal.get().getUserId());
        wrapper.set("status", 1);
        wrapper.set("update_date", LocalDateTime.now());
        this.update(wrapper);

        sendSocketMsg(UserThreadLocal.get().getUserId());
    }

    @Override
    public void sendMsg(SysMsg msg) {
        Integer userId = msg.getUserId();
        this.save(msg);
        if(null != userId){
            sendSocketMsg(userId);
        }
    }

    @Override
    public void delete(List<Long> ids) {
        QueryWrapper<SysMsg> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id", UserThreadLocal.get().getUserId());
        wrapper.in("id", ids);
        this.remove(wrapper);

        sendSocketMsg(UserThreadLocal.get().getUserId());
    }

    /**
     * 库存预警通知
     * @author 小啊刚
     * @date 2022-01-07
     */
    @Override
//    @Async
    public void earlyWarningNotice(List<VInOutRecordDetail> inOutRecordDetails, VInOutRecordMain inOutRecordMain, UserInfo userInfo) {
        Map<Integer, Double> inCountMap = new HashMap<>(); //物料去重
        SysUser adminUser = userService.getUserAdmin(userInfo.getCompanyId());
        if(adminUser != null) {
            for(VInOutRecordDetail detail : inOutRecordDetails) {
                try {
                    if(inCountMap.get(detail.getInventoryId()) == null) {
                        Double quantity  = inventoryInfoService.getInventorySum(detail.getInventoryId(), userInfo.getCompanyId());
                        System.out.println("现存量是多少=====" + quantity);
                        InInventory inventory = inventoryService.getById(detail.getInventoryId());
                        inCountMap.put(detail.getInventoryId(), quantity);
                        Long id = inOutRecordMain.getId();
                        if(inventory.getMinStorage() != null && inventory.getMinStorage().compareTo(BigDecimal.ZERO) > 0 && inventory.getMinStorage().compareTo(new BigDecimal(quantity)) > 0) { //最低库存预警
                            this.saveMsg(adminUser.getCompanyId(), adminUser.getId().intValue(), adminUser.getRealName(), userInfo.getUserId(), userInfo.getRealName(),
                                    4, "最低库存预警通知", "请注意！您的" + inventory.getInventoryName() + "物料现存量已低于最低库存!", id, "/inventory/setting/archives");
                        }

                        if(inventory.getMaxStorage() != null && inventory.getMaxStorage().compareTo(BigDecimal.ZERO) > 0 && inventory.getMaxStorage().compareTo(new BigDecimal(quantity)) < 0) { //最高库存预警
                            this.saveMsg(adminUser.getCompanyId(), adminUser.getId().intValue(), adminUser.getRealName(), userInfo.getUserId(), userInfo.getRealName(),
                                    4, "最高库存预警通知", "请注意！您的" + inventory.getInventoryName() + "物料现存量已高于最高库存!", id, "/inventory/setting/archives");
                        }

                        if(inventory.getSafeStorage() != null && inventory.getSafeStorage().compareTo(BigDecimal.ZERO) > 0 && inventory.getSafeStorage().compareTo(new BigDecimal(quantity)) > 0) { //安全库存预警
                            this.saveMsg(adminUser.getCompanyId(), adminUser.getId().intValue(), adminUser.getRealName(), userInfo.getUserId(), userInfo.getRealName(),
                                    4, "安全库存预警通知", "请注意！您的" + inventory.getInventoryName() + "物料现存量已低于安全库存!", id, "/inventory/setting/archives");
                        }
                    }
                } catch (Exception e) {
                    log.debug("库存预警通知失败");
                }
            }
        }
    }

    @Override
    @Async
    public void inOutSubmitMsgNotice(VInOutRecordMain inOutRecordMain) {
        String dataSource = inOutRecordMain.getDataSource();
        Integer businessType = inOutRecordMain.getBusinessType();
        Integer state = inOutRecordMain.getVoucherState();
        String content;
        if(state.equals(0)) {
            content = inOutRecordMain.getSubmitUserName() + "已提交单据，单据号为" + inOutRecordMain.getVoucherCode() + ",请前往查看、审核!";
        } else {
            content = inOutRecordMain.getSubmitUserName() + "已审核单据，单据号为" + inOutRecordMain.getVoucherCode() + ",请前往查看、确认!";
        }

        if(dataSource.equals("PurchaseReceiveVoucher") && businessType.equals(0)) { //采购入库
            sendInOutMsg("purchaseIn:" + (state == 0 ? "examine" : "confirmIn"), inOutRecordMain, "采购入库单通知", content);
        }

        if(businessType.equals(99)) { //采购退货
            sendInOutMsg("purchaseReturn:" + (state == 0 ? "examine" : "confirmInRet"), inOutRecordMain, "采购退货单通知", content);
        }

//        if(inOutRecordMain.getDataSource().equals("SaleDelivery") && inOutRecordMain.getBusinessType().equals(0)) { //销售发货通知单
//            sendInOutMsg("saleDeliveryWarehouse:examine", inOutRecordMain, "销售发货单通知");
//        }

        if(dataSource.equals("SaleDispatchVoucher") && businessType.equals(0)) { //销售出库单
            sendInOutMsg("saleOut:" + (state == 0 ? "examine" : "confirmOut"), inOutRecordMain, "销售出库单通知", content);
        }

//        if(inOutRecordMain.getDataSource().equals("SaleDelivery") && inOutRecordMain.getBusinessType().equals(98)) { //销售退货通知单
//            sendInOutMsg("billSaleReturn:examine", inOutRecordMain, "销售退货通知单通知");
//        }

        if(businessType.equals(98)) { //销售退货
            sendInOutMsg("billSaleOutRet:" + (state == 0 ? "examine" : "comfirmOutRet"), inOutRecordMain, "销售退货单通知", content);
        }

        if(dataSource.equals("MaterialDispatchVoucher") && businessType.equals(0)) { //生产领料
            sendInOutMsg("materialOut:" + (state == 0 ? "examine" : "confirmOut"), inOutRecordMain, "生产领料单通知", content);
        }

        if(dataSource.equals("MaterialDispatchVoucher") && businessType.equals(5)) { //生产退料
            sendInOutMsg("materialOutRet:" + (state == 0 ? "examine" : "confirmIn"), inOutRecordMain, "生产退料单通知", content);
        }

        if(dataSource.equals("ProductReceiveVoucher") && businessType.equals(0)) { //生产产品入库
            sendInOutMsg("productIn:" + (state == 0 ? "examine" : "confirmIn"), inOutRecordMain, "生产产品入库单通知", content);
        }

        if(dataSource.equals("ProductReceiveVoucher") && businessType.equals(94)) { //生产产品退库
            sendInOutMsg("productOut:" + (state == 0 ? "examine" : "confirmOut"), inOutRecordMain, "生产产品退库单通知", content);
        }

        if(dataSource.equals("DelegateDispatchVoucher") && businessType.equals(0)) { //委外领料
            sendInOutMsg("delegateOut:" + (state == 0 ? "examine" : "confirmOut"), inOutRecordMain, "委外领料单通知", content);
        }

        if(dataSource.equals("DelegateDispatchVoucher") && businessType.equals(5)) { //委外退料
            sendInOutMsg("delegateOutRet:" + (state == 0 ? "examine" : "confirmIn"), inOutRecordMain, "委外退料单通知", content);
        }

        if(dataSource.equals("DelegateReceiveVoucher") && businessType.equals(0)) { //委外产品入库
            sendInOutMsg("delegateIn:" + (state == 0 ? "examine" : "confirmIn"), inOutRecordMain, "委外产品入库单通知", content);
        }

        if(dataSource.equals("DelegateReceiveVoucher") && businessType.equals(5)) { //委外产品退库
            sendInOutMsg("delegateOuta:" + (state == 0 ? "examine" : "confirmOut"), inOutRecordMain, "委外产品退库单通知", content);
        }

        if(dataSource.equals("OtherDispatchVoucher") && businessType.equals(0)) { //其它入库
            sendInOutMsg("otherIn:" + (state == 0 ? "examine" : "confirmIn"), inOutRecordMain, "其它入库单通知", content);
        }

        if(dataSource.equals("OtherDispatchVoucher") && businessType.equals(5)) { //其它出库
            sendInOutMsg("otherOut:" + (state == 0 ? "examine" : "confirmOut"), inOutRecordMain, "其它出库单通知", content);
        }
    }

    @Override
    @Async
    public void inOutExamineMsgNotice(VInOutRecordMain inOutRecordMain) {
        inOutSubmitMsgNotice(inOutRecordMain);
    }

    @Override
    public void allocationNotice(VInOutAllocationMain outAllocationMain) {
        Long id = outAllocationMain.getId();
        if(outAllocationMain.getVoucherState().equals(0)) {
            sendVoucherMsg("applyTransfers:examine", outAllocationMain.getCompanyId(), outAllocationMain.getSubmitUserId(), outAllocationMain.getSubmitUserName(), "调拨单通知",
                    outAllocationMain.getSubmitUserName() + "已提交单据，单据号为" + outAllocationMain.getVoucherCode() + ",请前往查看、审核!", id);
        }

        if(outAllocationMain.getVoucherState().equals(1)) {
            sendVoucherMsg("applyTransfers:ratify", outAllocationMain.getCompanyId(), outAllocationMain.getReviewerUserId(), outAllocationMain.getReviewerUserName(), "调拨单通知",
                    outAllocationMain.getReviewerUserName() + "已审核单据，单据号为" + outAllocationMain.getVoucherCode() + ",请前往查看、批准!", id);
        }

        if(outAllocationMain.getVoucherState().equals(2)) {
            sendVoucherMsg("transfers:allot", outAllocationMain.getCompanyId(), outAllocationMain.getApprovalUserId(), outAllocationMain.getApprovalUserName(), "调拨单通知",
                    outAllocationMain.getApprovalUserName() + "已批准单据，单据号为" + outAllocationMain.getVoucherCode() + ",请前往查看、调拨!", id);
        }
    }

    @Override
    public void saleDeliveryNotice(VSaleDeliveryMain saleDeliveryMain) {
        if(saleDeliveryMain.getBusinessType().equals(0)) {
            sendVoucherMsg("saleDeliveryWarehouse:examine", saleDeliveryMain.getCompanyId(), saleDeliveryMain.getSubmitUserId(), saleDeliveryMain.getSubmitUserName(), "发货通知单通知",
                    saleDeliveryMain.getSubmitUserName() + "已提交单据，单据号为" + saleDeliveryMain.getVoucherCode() + ",请前往查看、审核!", saleDeliveryMain.getId());
        } else {
            sendVoucherMsg("billSaleReturn:examine", saleDeliveryMain.getCompanyId(), saleDeliveryMain.getSubmitUserId(), saleDeliveryMain.getSubmitUserName(), "退货通知单通知",
                    saleDeliveryMain.getSubmitUserName() + "已提交单据，单据号为" + saleDeliveryMain.getVoucherCode() + ",请前往查看、审核!", saleDeliveryMain.getId());
        }
    }

    @Override
    public void checkMsgNotice(VInventoryCheckMain inventoryCheckMain) {
        if(inventoryCheckMain.getVoucherState().equals(1)) {
            sendVoucherMsg("InventoryWork:panel", inventoryCheckMain.getCompanyId(), inventoryCheckMain.getReviewerUserId(), inventoryCheckMain.getReviewerUserName(), "盘点作业通知",
                    inventoryCheckMain.getReviewerUserName() + "已复核单据，单据号为" + inventoryCheckMain.getVoucherCode() + ",请前往查看、监盘!", inventoryCheckMain.getId());
        } else {
            sendVoucherMsg("InventoryWork:panel", inventoryCheckMain.getCompanyId(), inventoryCheckMain.getApproveUserId(), inventoryCheckMain.getApproveUserName(), "盘点作业通知",
                    inventoryCheckMain.getApproveUserName() + "已监盘单据，单据号为" + inventoryCheckMain.getVoucherCode() + ",请前往查看、批准!", inventoryCheckMain.getId());
        }
    }

    public void sendInOutMsg(String permission, VInOutRecordMain inOutRecordMain, String title, String content){
        MenuVo menuVo = userService.getByMenuPermission(inOutRecordMain.getCompanyId(), permission);
        if(menuVo != null) {
            List<UserInfo> userInfos = menuVo.getUserInfoList();
            SysMenu menu = menuVo.getMenu();
            Integer createUserId = inOutRecordMain.getVoucherState() == 0 ? inOutRecordMain.getSubmitUserId() : inOutRecordMain.getReviewerUserId();
            String createUserName = inOutRecordMain.getVoucherState() == 0 ? inOutRecordMain.getSubmitUserName() : inOutRecordMain.getReviewerUserName();
            for(UserInfo userInfo : userInfos) {
                this.saveMsg(inOutRecordMain.getCompanyId(), userInfo.getUserId(), userInfo.getRealName(), createUserId, createUserName, 4, title, content, inOutRecordMain.getId(), menu.getViewPath());
            }
        }
    }

    public void sendVoucherMsg(String permission, Integer companyId, Integer creatUserId, String createUserName, String title, String content, Long voucherId) {
        MenuVo menuVo = userService.getByMenuPermission(companyId, permission);
        if(menuVo != null) {
            List<UserInfo> userInfos = menuVo.getUserInfoList();
            SysMenu menu = menuVo.getMenu();
            for(UserInfo userInfo : userInfos) {
                this.saveMsg(companyId, userInfo.getUserId(), userInfo.getRealName(), creatUserId, createUserName, 4, title, content, voucherId, menu.getViewPath());
            }
        }
    }

    public void saveMsg(Integer companyId, Integer userId, String realName, Integer createUserId, String createUserName, Integer type, String title, String content, Long voucherId, String menuHref) {
//       if(!userId.equals(createUserId)) {
//       }
        SysMsg msg = new SysMsg();
        msg.setTitle(title);
        msg.setContent(content);
        msg.setCompanyId(companyId);
        msg.setUserId(userId);
        msg.setUserName(realName);
        msg.setType(type);
        msg.setCreateUserId(createUserId);
        msg.setCreateUserName(createUserName);
        msg.setMenuHref(menuHref);
        msg.setVoucherId(voucherId);
        this.save(msg);
        sendSocketMsg(userId);
    }

    /**
     * 推送数量消息
     * @author 小啊刚
     * @date 2022-01-12
     */
    public void sendSocketMsg(Integer userId) {
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("user_id", userId);
        wrapper.eq("status", 0);
        WebSocketResult<Integer> webSocketResult = new WebSocketResult<>();
        webSocketResult.setBusinessType("NotReadMsg");
        webSocketResult.setData(count(wrapper));
        socketService.sendOneMessage(userId.toString(), JSON.toJSONString(webSocketResult));
    }
}
